using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;

public class Tetris
{
    public class TetrisItem
    {
        private Color m_Col;
        private bool m_HasBlock;

        public bool HasBlock
        {
            get { return m_HasBlock; }
        }

        public Color Col
        {
            get
            {
                return m_Col;
            }
        }

        public void Reset()
        {
            m_HasBlock = false;
            m_Col = Color.white;
        }

        public void Modify(Color col)
        {
            m_Col = col;
            m_HasBlock = true;
        }

    }

    public TetrisItem[,] m_ItemArr;
    public int XLen
    {
        get
        {
            return m_XLen;
        }
    }

    public int YLen
    {
        get
        {
            return m_YLen;
        }
    }

    public List<int> CheckEliminate()
    {
        List<int> ret = new List<int>();
        for (int i = 0; i < m_YLen; i++)
        {
            bool line = true;
            for (int j = 0; j < m_XLen; j++)
            {
                TetrisItem item = m_ItemArr[j, i];
                if (item.HasBlock == false)
                {
                    line = false;
                    break;
                }
            }

            if (line)
            {
                ret.Add(i);
            }
        }

        return ret;
    }

    public bool DoEliminate()
    {
        List<int> lines = CheckEliminate();
        if (lines.Count == 0)
        {
            return false;
        }
        for (int i = lines.Count - 1; i >= 0; i--)
        {
            DeleteOneLine(lines[i]);
        }

        return true;
    }

    public void InsertBlock(BlockItem blockItem)
    {
        List<TetrisCoord> coordLst = blockItem.GetCoordLst();
        for (int i = 0; i < coordLst.Count; i++)
        {
            TetrisCoord coord = coordLst[i];
            Color col = ConvertBlockType2Color(blockItem.BlockType);
            m_ItemArr[coord.X, coord.Y].Modify(col);
        }
    }

    private int m_XLen;
    private int m_YLen;

    private int ConvertCoord2Idx(int x, int y)
    {
        return y * m_XLen + x;
    }

    private void DeleteOneLine(int line)
    {
        for (int i = 0; i < m_XLen; i++)
        {
            for (int j = line; j < m_YLen - 1; j++)
            {
                m_ItemArr[i, j] = m_ItemArr[i, j + 1];
            }
            m_ItemArr[i, m_YLen - 1].Reset();
        }
    }

    private Color ConvertBlockType2Color(EBlockType blockType)
    {
        throw new NotImplementedException();
    }
}

abstract public class BlockItem
{
    public EBlockType BlockType
    {
        get
        {
            return m_BlockType;
        }
    }
    public EDirection Direction
    {
        get { return m_Direction; }
    }
    public abstract List<TetrisCoord> GetCoordLst();
    public void Rotate()
    {
        m_Direction = (EDirection)Mathf.Repeat((int)m_Direction + 1, 3);
    }
    protected EBlockType m_BlockType;
    protected EDirection m_Direction;

}

public class BlockItemS : BlockItem
{
    public BlockItemS()
    {
        m_BlockType = EBlockType.eS;
    }
    public override List<TetrisCoord> GetCoordLst()
    {
        throw new NotImplementedException();
    }
}

public class BlockItemZ : BlockItem
{
    public BlockItemZ()
    {
        m_BlockType = EBlockType.eZ;
    }
    public override List<TetrisCoord> GetCoordLst()
    {
        throw new NotImplementedException();
    }
}

public class BlockItemI : BlockItem
{
    public BlockItemI()
    {
        m_BlockType = EBlockType.eI;
    }
    public override List<TetrisCoord> GetCoordLst()
    {
        throw new NotImplementedException();
    }
}

public class BlockItemL : BlockItem
{
    public BlockItemL()
    {
        m_BlockType = EBlockType.eL;
    }
    public override List<TetrisCoord> GetCoordLst()
    {
        throw new NotImplementedException();
    }
}

public class BlockItemF : BlockItem
{
    public BlockItemF()
    {
        m_BlockType = EBlockType.eL;
    }
    public override List<TetrisCoord> GetCoordLst()
    {
        throw new NotImplementedException();
    }
}

public class BlockItemO : BlockItem
{
    public BlockItemO()
    {
        m_BlockType = EBlockType.eO;
    }
    public override List<TetrisCoord> GetCoordLst()
    {
        throw new NotImplementedException();
    }
}

public class BlockItemT : BlockItem
{
    public BlockItemT()
    {
        m_BlockType = EBlockType.eT;
    }
    public override List<TetrisCoord> GetCoordLst()
    {
        throw new NotImplementedException();
    }
}

public enum EBlockType
{
    eS = 0,
    eZ,
    eI,
    eL,
    eF,
    eO,
    eT,
}

public enum EDirection
{
    eTop = 0,
    eRight,
    eBottom,
    eLeft,
}

public struct TetrisCoord
{
    public int X
    {
        get
        {
            return m_X;
        }
    }

    public int Y
    {
        get
        {
            return m_Y;
        }
    }

    public TetrisCoord(int x, int y)
    {
        m_X = x;
        m_Y = y;
    }

    public TetrisCoord(Vector2 v)
    {
        m_X = (int)v.x;
        m_Y = (int)v.y;
    }

    public static implicit operator TetrisCoord(Vector2 v)
    {
        return new TetrisCoord((int)v.x, (int)v.y);
    }

    private int m_X;
    private int m_Y;
}